package com.quiz.bis.generate;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.quiz.bis.domain.model.*;
import com.quiz.bis.mapper.*;
import com.quiz.bis.util.HtmlUtils;
import com.quiz.common.utils.uuid.IdUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StopWatch;


import java.util.*;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.Collectors;

@Slf4j
@Service
public class QuestionDataGenerator {

    @Autowired
    private QuestionTypeMapper questionTypeMapper;
    @Autowired
    private QuestionMapper questionMapper;
    @Autowired
    private QuestionOptionMapper questionOptionMapper;
    @Autowired
    private QuestionAnswerMapper questionAnswerMapper;
    @Autowired
    private TagMapper tagMapper;
    @Autowired
    private QuestionTagRelationMapper questionTagRelationMapper;
    @Autowired
    private QuestionCategoryMapper questionCategoryMapper;
    @Autowired
    private QuestionCategoryRelationMapper questionCategoryRelationMapper;

    // 配置常量
    private static final int BATCH_SIZE = 500;
    private static final String[] COLORS = {"#FF0000", "#00FF00", "#0000FF", "#FFFF00", "#FF00FF", "#00FFFF"};
    private static final List<String> OPTION_TEMPLATES = Arrays.asList(
            "这是选项内容模板1，包含一些描述性文字",
            "选项内容模板2可能包含不同的描述方式",
            "第三种选项模板可能包含更详细的内容",
            "最后一个选项模板通常是最长的描述"
    );
    private static final String[] DIFFICULTY_NAMES = {"容易", "偏易", "中等", "偏难", "困难"};

    /**
     * 生成题目数据
     */
    @Transactional(rollbackFor = Exception.class)
    public QuestionGenerateResultVo generate(QuestionGenerateConfig config) {
        StopWatch stopWatchSum = new StopWatch();
        StopWatch stopWatch = new StopWatch();
        stopWatchSum.start("生成题目数据");

        QuestionGenerateResultVo result = new QuestionGenerateResultVo();
        try {
            // 1. 准备基础数据
            List<QuestionType> allTypes = questionTypeMapper.selectList(null);
            Map<String, QuestionType> typeMap = allTypes.stream()
                    .collect(Collectors.toMap(QuestionType::getCode, t -> t));

            // 2. 生成分类和知识点
            stopWatch.start("生成分类和知识点");
            List<CategoryStructure> subjectKnowledgeMap = generateCategoriesAndKnowledges(
                    config.getSubjects(),
                    config.getSubCategoriesPerSubject(),
                    config.getKnowledgesPerSubCategory()
            );
            stopWatch.stop();

            // 3. 确保难度标签存在
            stopWatch.start("生成难度标签");
            ensureDifficultyTagsExist();
            stopWatch.stop();

            // 4. 生成题目
            stopWatch.start("生成题目");
            for (Map.Entry<String, Integer> entry : config.getQuestionCounts().entrySet()) {
                if (entry.getValue() > 0) {
                    QuestionType type = typeMap.get(entry.getKey());
                    if (type == null) {
                        throw new RuntimeException("题型编码不存在: " + entry.getKey());
                    }
                    generateQuestions(type, entry.getValue(), subjectKnowledgeMap, config.getDifficultyDistribution(), result);
                }
            }
            stopWatch.stop();

            result.setSuccess(true);
            log.info("题目数据生成成功，总计生成: {} 道题", result.getTotalGenerated());
        } catch (Exception e) {
            log.error("题目数据生成失败", e);
            result.setSuccess(false);
            result.setErrorMessage(e.getMessage());
            throw e;
        } finally {
            stopWatchSum.stop();
            log.info(stopWatchSum.prettyPrint());
            result.setExecutionTime(stopWatchSum.getTotalTimeSeconds());
        }

        return result;
    }

    /**
     * 生成分类和知识点
     */
    // 修改后的生成方法
    private List<CategoryStructure> generateCategoriesAndKnowledges(List<String> subjects,
                                                                    int subCategoriesPerSubject,
                                                                    int knowledgesPerSubCategory) {
        List<CategoryStructure> structures = new ArrayList<>();

        for (String subject : subjects) {
            CategoryStructure structure = new CategoryStructure();
            structure.setSubjectName(subject);

            // 创建学科分类
            QuestionCategory subjectCategory = buildCategory(subject,
                    "主控节点",
                    "subject_" + subject + "_" + IdUtils.simpleUUID(),
                    0L,
                    "0",
                    0);
            questionCategoryMapper.insert(subjectCategory);
            structure.setSubjectId(subjectCategory.getId());

            // 创建子分类
            List<SubCategory> subCategories = new ArrayList<>();
            for (int i = 1; i <= subCategoriesPerSubject; i++) {
                SubCategory subCategory = new SubCategory();
                String subCategoryName = subject + "子分类" + i;
                subCategory.setName(subCategoryName);

                QuestionCategory category = buildCategory(
                        subCategoryName,
                        subject,
                        "sub_" + subject + i + "_" + IdUtils.simpleUUID(),
                        subjectCategory.getId(),
                        subjectCategory.getLevelPath(),
                        0
                );
                questionCategoryMapper.insert(category);
                subCategory.setId(category.getId());

                // 创建知识点
                List<KnowledgePoint> knowledgePoints = new ArrayList<>();
                for (int j = 1; j <= knowledgesPerSubCategory; j++) {
                    KnowledgePoint point = new KnowledgePoint();
                    String knowledgeName = subCategoryName + "-知识点" + j;
                    point.setName(knowledgeName);

                    QuestionCategory knowledge = buildCategory(
                            knowledgeName,
                            subCategoryName,
                            "knowledge_" + subject + "_" + i + "_" + j + "_" + IdUtils.simpleUUID(),
                            category.getId(),
                            category.getLevelPath(),
                            1
                    );
                    questionCategoryMapper.insert(knowledge);
                    point.setId(knowledge.getId());

                    knowledgePoints.add(point);
                }
                subCategory.setKnowledgePoints(knowledgePoints);
                subCategories.add(subCategory);
            }
            structure.setSubCategories(subCategories);
            structures.add(structure);
        }

        return structures;
    }


    private QuestionCategory buildCategory(String name, String parentName, String code, Long parentId, String parentPath, int isKnowledge) {
        QuestionCategory category = new QuestionCategory();
        long id = IdWorker.getId();
        category.setId(id);
        category.setName(name);
        category.setCode(code);
        category.setParentId(parentId);
        category.setParentName(parentName);
        category.setLevelPath(parentPath + "," + id);
        category.setIsKnowledge(isKnowledge);
        category.setSort(0);
        category.setDelFlag(0);
        category.setDeptId(100L);
        category.setCreateBy("1");
        category.setUpdateBy("1");
        category.setCreateTime(new Date());
        category.setUpdateTime(new Date());
        return category;
    }

    private void batchInsertCategories(List<QuestionCategory> categories) {
        if (categories.isEmpty()) return;

        // 分批插入
        int total = categories.size();
        for (int i = 0; i < total; i += BATCH_SIZE) {
            int end = Math.min(i + BATCH_SIZE, total);
            List<QuestionCategory> subList = categories.subList(i, end);
            questionCategoryMapper.insertBatch(subList);
        }
    }

    /**
     * 确保难度标签存在
     */
    private void ensureDifficultyTagsExist() {
        List<Tag> existingTags = tagMapper.selectList(new LambdaQueryWrapper<Tag>()
                .eq(Tag::getType, "difficulty"));

        Set<String> existingNames = existingTags.stream()
                .map(Tag::getName)
                .collect(Collectors.toSet());

        List<Tag> tagsToInsert = new ArrayList<>();
        for (int i = 0; i < DIFFICULTY_NAMES.length; i++) {
            if (!existingNames.contains(DIFFICULTY_NAMES[i])) {
                Tag tag = new Tag();
                tag.setName(DIFFICULTY_NAMES[i]);
                tag.setType("difficulty");
                tag.setColor(COLORS[i % COLORS.length]);
                tag.setSort(i + 1);
                tag.setDelFlag(0);
                tag.setDeptId(100L);
                tag.setCreateBy("1");
                tag.setUpdateBy("1");
                tag.setCreateTime(new Date());
                tag.setUpdateTime(new Date());
                tagsToInsert.add(tag);
            }
        }

        if (!tagsToInsert.isEmpty()) {
            tagMapper.insertBatch(tagsToInsert);
        }
    }

    /**
     * 生成题目
     */
    private void generateQuestions(QuestionType type, int count,
                                   List<CategoryStructure> categoryStructures,
                                   List<Integer> difficultyDistribution,
                                   QuestionGenerateResultVo result) {

        List<Question> questionsToInsert = new ArrayList<>();
        List<QuestionOption> optionsToInsert = new ArrayList<>();
        List<QuestionAnswer> answersToInsert = new ArrayList<>();
        List<QuestionTagRelation> tagRelationsToInsert = new ArrayList<>();
        List<QuestionCategoryRelation> categoryRelationsToInsert = new ArrayList<>();
        List<QuestionStatistics> statisticsToInsert = new ArrayList<>();

        Random random = new Random();
        int generatedCount = 0;

        while (generatedCount < count) {




            // 3. 根据难度分布随机选择难度
            int difficult = getRandomDifficulty(difficultyDistribution);

            // 4. 生成题目内容
            String s = IdUtils.fastSimpleUUID();
            String title = generateQuestionTitle(type.getName(), s, ++generatedCount);
            String content = generateQuestionContent(type.getName(), s, generatedCount);
            String contentText = HtmlUtils.htmlToText(content);
            String answer = generateQuestionAnalysis(type.getName(), s, generatedCount);
            String answerText = HtmlUtils.htmlToText(answer);
            // 5. 构建题目对象
            Question question = new Question();
            question.setTitle(title);
            question.setTypeId(type.getId());
            question.setContent(content);
            question.setContentText(contentText);
            question.setAnalysis(answer);
            question.setAnalysisText(answerText);
            question.setStatus(1);
            question.setDifficult(difficult);
            question.setDelFlag(0);
            question.setDeptId(100L);
            question.setCreateBy("1");
            question.setUpdateBy("1");
            question.setCreateTime(new Date());
            question.setUpdateTime(new Date());
            questionsToInsert.add(question);

            // 6. 如果是批量插入的最后一批或者达到总数，执行插入
            if (questionsToInsert.size() >= BATCH_SIZE || generatedCount >= count) {
                // 批量插入题目
                questionMapper.insertBatch(questionsToInsert);

                // 处理关联关系
                for (Question q : questionsToInsert) {
                    // 1. 随机选择学科
                    CategoryStructure subject = categoryStructures.get(
                            random.nextInt(categoryStructures.size()));

                    //  随机选择1-3个知识点（可根据需要调整数量范围）
                    List<KnowledgePoint> selectedKnowledges = new ArrayList<>();
                    int knowledgeCount = 1 + random.nextInt(4); // 每题1-3个知识点

                    //  收集所有可能的知识点
                    List<KnowledgePoint> allKnowledges = new ArrayList<>();
                    for (SubCategory subCategory : subject.getSubCategories()) {
                        allKnowledges.addAll(subCategory.getKnowledgePoints());
                    }

                    //  2.2随机选择不重复的知识点
                    Collections.shuffle(allKnowledges);
                    for (int i = 0; i < Math.min(knowledgeCount, allKnowledges.size()); i++) {
                        selectedKnowledges.add(allKnowledges.get(i));
                    }
                    // 为每道题目关联多个知识点
                    for (KnowledgePoint knowledge : selectedKnowledges) {
                        QuestionCategoryRelation categoryRelation = new QuestionCategoryRelation();
                        categoryRelation.setQuestionId(q.getId());
                        categoryRelation.setCategoryId(knowledge.getId()); // 使用知识点ID
                        categoryRelation.setIsKnowledge(1); // 标记为知识点
                        categoryRelation.setDelFlag(0);
                        categoryRelation.setDeptId(100L);
                        categoryRelation.setCreateBy("1");
                        categoryRelation.setUpdateBy("1");
                        categoryRelation.setCreateTime(new Date());
                        categoryRelation.setUpdateTime(new Date());
                        categoryRelationsToInsert.add(categoryRelation);
                    }

                    // 关联难度标签
                    QuestionTagRelation tagRelation = new QuestionTagRelation();
                    tagRelation.setQuestionId(q.getId());
                    tagRelation.setTagId((long) q.getDifficult());
                    tagRelation.setDelFlag(0);
                    tagRelation.setDeptId(100L);
                    tagRelation.setCreateBy("1");
                    tagRelation.setUpdateBy("1");
                    tagRelation.setCreateTime(new Date());
                    tagRelation.setUpdateTime(new Date());
                    tagRelationsToInsert.add(tagRelation);

                    // 生成选项或答案
                    if (type.getHasOption() > 0) {
                        optionsToInsert.addAll(generateQuestionOptions(q.getId(), type.getHasOption() == 2));
                    } else if (type.getHasAnswer() == 1) {
                        answersToInsert.add(generateQuestionAnswer(q.getId()));
                    }

                    // 生成统计信息
                    statisticsToInsert.add(generateQuestionStatistics(q.getId()));
                }

                // 批量插入关联数据
                if (!optionsToInsert.isEmpty()) {
                    questionOptionMapper.insertBatch(optionsToInsert);
                    optionsToInsert.clear();
                }
                if (!answersToInsert.isEmpty()) {
                    questionAnswerMapper.insertBatch(answersToInsert);
                    answersToInsert.clear();
                }
                if (!tagRelationsToInsert.isEmpty()) {
                    questionTagRelationMapper.insertBatch(tagRelationsToInsert);
                    tagRelationsToInsert.clear();
                }
                if (!categoryRelationsToInsert.isEmpty()) {
                    questionCategoryRelationMapper.insertBatch(categoryRelationsToInsert);
                    categoryRelationsToInsert.clear();
                }

                result.setTotalGenerated(result.getTotalGenerated() + questionsToInsert.size());
                questionsToInsert.clear();

                log.info("已生成 {} 道 {} (共需生成 {} 道)", generatedCount, type.getName(), count);
            }
        }
    }

    private int getRandomDifficulty(List<Integer> distribution) {
        int randomValue = ThreadLocalRandom.current().nextInt(100);
        int sum = 0;
        for (int i = 0; i < distribution.size(); i++) {
            sum += distribution.get(i);
            if (randomValue < sum) {
                return i + 1;
            }
        }
        return distribution.size();
    }

    private List<QuestionOption> generateQuestionOptions(Long questionId, boolean isMultiple) {
        List<QuestionOption> options = new ArrayList<>();
        int optionCount = isMultiple ? 4 + ThreadLocalRandom.current().nextInt(2) : 4;
        char[] optionCodes = {'A', 'B', 'C', 'D', 'E', 'F'};

        // 确定正确答案
        int correctCount = isMultiple ? 1 + ThreadLocalRandom.current().nextInt(3) : 1;
        Set<Integer> correctIndices = new HashSet<>();
        while (correctIndices.size() < correctCount) {
            correctIndices.add(ThreadLocalRandom.current().nextInt(optionCount));
        }

        for (int i = 0; i < optionCount; i++) {
            String content = "<p>" + OPTION_TEMPLATES.get(ThreadLocalRandom.current().nextInt(OPTION_TEMPLATES.size())) + "</p>";
            String contentText = HtmlUtils.htmlToText(content);

            QuestionOption option = new QuestionOption();
            option.setQuestionId(questionId);
            option.setOptionCode(String.valueOf(optionCodes[i]));
            option.setContent(content);
            option.setContentText(contentText);
            option.setIsCorrect(correctIndices.contains(i) ? 1 : 0);
            option.setSort(i);
            option.setDelFlag(0);
            option.setDeptId(100L);
            option.setCreateBy("1");
            option.setUpdateBy("1");
            option.setCreateTime(new Date());
            option.setUpdateTime(new Date());
            options.add(option);
        }

        return options;
    }

    private QuestionAnswer generateQuestionAnswer(Long questionId) {
        String answer = "<p>这是" + (ThreadLocalRandom.current().nextInt(5) + 1) + "个可能的答案示例。</p>";
        String answerText = HtmlUtils.htmlToText(answer);

        QuestionAnswer questionAnswer = new QuestionAnswer();
        questionAnswer.setQuestionId(questionId);
        questionAnswer.setContent(answer);
        questionAnswer.setContentText(answerText);
        questionAnswer.setSort(0);
        questionAnswer.setDelFlag(0);
        questionAnswer.setDeptId(100L);
        questionAnswer.setCreateBy("1");
        questionAnswer.setUpdateBy("1");
        questionAnswer.setCreateTime(new Date());
        questionAnswer.setUpdateTime(new Date());
        return questionAnswer;
    }

    private QuestionStatistics generateQuestionStatistics(Long questionId) {
        QuestionStatistics statistics = new QuestionStatistics();
        statistics.setQuestionId(questionId);
        statistics.setViewCount(ThreadLocalRandom.current().nextInt(1000));
        statistics.setUseCount(ThreadLocalRandom.current().nextInt(500));
        statistics.setPaperCount(ThreadLocalRandom.current().nextInt(200));
        statistics.setCorrectCount(ThreadLocalRandom.current().nextInt(400));
        statistics.setWrongCount(ThreadLocalRandom.current().nextInt(100));
        statistics.setDelFlag(0);
        statistics.setDeptId(100L);
        statistics.setCreateBy("1");
        statistics.setUpdateBy("1");
        statistics.setCreateTime(new Date());
        statistics.setUpdateTime(new Date());
        return statistics;
    }

//    private QuestionVersion generateQuestionVersion(Question question, Long typeId, Long knowledgeId) {
//        String tagsJson = String.format("{\"knowledge\": [%d], \"difficulty\": [%d]}",
//                knowledgeId, question.getDifficult());
//
//        QuestionVersion version = new QuestionVersion();
//        version.setQuestionId(question.getId());
//        version.setVersion(1);
//        version.setTitle(question.getTitle());
//        version.setContent(question.getContent());
//        version.setTypeId(typeId);
//        version.setTagsJson(tagsJson);
//        version.setDelFlag(0);
//        version.setDeptId(100L);
//        version.setCreateBy("1");
//        version.setUpdateBy("1");
//        version.setCreateTime(new Date());
//        version.setUpdateTime(new Date());
//        return version;
//    }

    private String generateQuestionTitle(String typeName, String subject, int index) {
        return String.format("%s题目示例 %d (%s)", typeName, index, subject);
    }

    private String generateQuestionContent(String typeName, String subject, int index) {
        return String.format("<p>这是关于%s的%s题目内容示例 %d。</p><p>题目详细描述...</p>",
                subject, typeName, index);
    }

    private String generateQuestionAnalysis(String typeName, String subject, int index) {
        return String.format("<p>这是关于%s的%s题目解析 %d。</p><p>题目解析详情为。。。</p>",
                subject, typeName, index);
    }
}